﻿using System;
using System.Text;
using System.Windows;
using System.Windows.Forms;
using System.IO;
using System.Windows.Media.Imaging;
using AForge.Video.DirectShow;
using System.Runtime.InteropServices;
using System.Drawing;
using AForge.Video.FFMPEG;
using System.Text.RegularExpressions;
using System.Drawing.Drawing2D;


namespace OperateCamera
{
    

    public partial class Form1 : Form
    {
        private FilterInfoCollection videoDevices;
        private VideoCaptureDevice videoSource;
        private delegate void WriteLabelDelegate(object entry);

        private bool stopREC = true;
        private bool createNewFile = true;
        int frameRate = 12; //默认帧率
        private VideoFileWriter videoWriter = null;
        private string videoFileFullPath = string.Empty; //视频文件全路径
        private string imageFileFullPath = string.Empty; //图像文件全路径
        private string videoPath = @"E:\video\"; //视频文件路径
        private string videoFileName = string.Empty; //视频文件名
        private string drawDate = string.Empty;
        private VideoFileReader _reader;
        private VideoFileWriter _writer;

        static int intFlag = 0;

        public IntPtr handler;

        private SQLiteDBHelper db;
        StringBuilder keyValue;

        [DllImport("gdi32")]
        static extern int DeleteObject(IntPtr o);


        public Form1()
        {
            System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
            
        }
        
        private void Form1_Load(object sender, EventArgs e)
        {
            //初始化数据库
            db = new SQLiteDBHelper(Environment.CurrentDirectory + "\\data\\database.db3");
            
            try
            {
                // 枚举所有视频输入设备
                videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);

                if (videoDevices.Count == 0)
                    throw new ApplicationException();


                foreach (FilterInfo device in videoDevices)
                {
                    tscbxCameras.Items.Add(device.Name);
                }

                tscbxCameras.SelectedIndex = 0;

            }
            catch (ApplicationException)
            {
                tscbxCameras.Items.Add("没有找到摄像头");
                videoDevices = null;
            }

            //载入热键
            register_hotkey();

            //显示当前选择的保存路径
            this.tb_filePath.Text = db.C("save_path")[0][1];
            videoPath = db.C("save_path")[0][1] + "\\video\\";
            if (!common.ck()) {
                this.Opacity = 0;
                this.ShowInTaskbar = false;
                Form f2 = new Form2(this);
                f2.ShowDialog();

                
            }
            showHotKey();
        }


        private void showHotKey() {


            string hk = db.C("hotkey")[0][1];

            hk = hk.Replace("[", "");
            hk = hk.Replace("]", "");
            string[] sArray = Regex.Split(hk, ",", RegexOptions.IgnoreCase);

            hotkey.KeyModifiers k;
            switch (Int32.Parse(sArray[0]))
            {

                case 0: k = hotkey.KeyModifiers.None; break;
                case 1: k = hotkey.KeyModifiers.Alt; break;
                case 2: k = hotkey.KeyModifiers.Ctrl; break;
                case 4: k = hotkey.KeyModifiers.Shift; break;
                case 8: k = hotkey.KeyModifiers.WindowsKey; break;
                default: k = hotkey.KeyModifiers.None; break;
            }


            this.textBox1.Text = "" + k + "+" + (Keys)Int32.Parse(sArray[1]);
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            CameraConn();
        }

        public void connectCam() {

            CameraConn();
        
        }

        //连接摄像头
        private void CameraConn()
        {

            VideoCaptureDevice videoSource = new VideoCaptureDevice(videoDevices[tscbxCameras.SelectedIndex].MonikerString);
            videoSource.DesiredFrameSize = new System.Drawing.Size(320, 240);
            videoSource.DesiredFrameRate = 1;
            //videoSource.NewFrame -= new videoSourcePlayer1_NewFrame();  

            videoSourcePlayer.VideoSource = videoSource;
            videoSourcePlayer.Start();
        }

        //关闭摄像头
        private void btnClose_Click(object sender, EventArgs e)
        {

   
            videoSourcePlayer.SignalToStop();
            videoSourcePlayer.WaitForStop();
        }

        //主窗体关闭
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            btnClose_Click(null, null);
        }

        //拍照
        private void Photograph_Click(object sender, EventArgs e)
        {

            GetPic();
        }

        public  byte[] Tinvoke() {

            byte[] img = new byte[100];
            this.Invoke(new EventHandler(delegate
            {

                img = GetPicByFrame();
            }));

            return img;

        }
        //实时影像功能
        public   byte[] GetPicByFrame() {

     
            try
            {
                if (videoSourcePlayer.IsRunning)
                {
                    IntPtr ip = videoSourcePlayer.GetCurrentVideoFrame().GetHbitmap();

                    BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                                    ip,
                                    IntPtr.Zero,
                                     Int32Rect.Empty,
                                    BitmapSizeOptions.FromEmptyOptions());
                    DeleteObject(ip);
                    PngBitmapEncoder pE = new PngBitmapEncoder();

                    using (MemoryStream ms = new MemoryStream())
                    {

                        Bitmap b = BitmapSourceToBitmap(bitmapSource);

                        b = GetImageThumb(b, common.DefaultSize); 

                        b.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
                        byte[] img = ms.GetBuffer();
                        ms.Close();
                        return img;

                    }



                }
                else {

                    Console.WriteLine("摄像头异常：未启动" );
                
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("摄像头异常：" + ex.Message);
                MessageBox.Show("摄像头异常：" + ex.Message);

            }


            return new byte[1];
            
        }

        //按尺寸压缩要图片
        public Bitmap GetImageThumb(Bitmap mg, System.Drawing.Size newSize)
        {
            double ratio = 0d;
            double myThumbWidth = 0d;
            double myThumbHeight = 0d;
            int x = 0;
            int y = 0;
            Bitmap bp;
            if ((mg.Width / Convert.ToDouble(newSize.Width)) > (mg.Height /
            Convert.ToDouble(newSize.Height)))
                ratio = Convert.ToDouble(mg.Width) / Convert.ToDouble(newSize.Width);
            else
                ratio = Convert.ToDouble(mg.Height) / Convert.ToDouble(newSize.Height);
            myThumbHeight = Math.Ceiling(mg.Height / ratio);
            myThumbWidth = Math.Ceiling(mg.Width / ratio);
            System.Drawing.Size thumbSize = new System.Drawing.Size((int)newSize.Width, (int)newSize.Height);

            bp = new Bitmap(newSize.Width, newSize.Height);
            x = (newSize.Width - thumbSize.Width) / 2;
            y = (newSize.Height - thumbSize.Height);
            System.Drawing.Graphics g = Graphics.FromImage(bp);

            //g.SmoothingMode = SmoothingMode.HighQuality;
            //g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            //g.PixelOffsetMode = PixelOffsetMode.HighQuality;

            g.SmoothingMode = SmoothingMode.HighSpeed;
            g.InterpolationMode = InterpolationMode.Low;
            g.PixelOffsetMode = PixelOffsetMode.HighSpeed;



            Rectangle rect = new Rectangle(x, y, (int)thumbSize.Width, (int)thumbSize.Height);
            g.DrawImage(mg, rect, 0, 0, mg.Width, mg.Height, GraphicsUnit.Pixel);
            return bp;
        }

        //图片BitmapSource 转 Bitmap
        public System.Drawing.Bitmap BitmapSourceToBitmap(BitmapSource s)
        {
            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(s.PixelWidth, s.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
            System.Drawing.Imaging.BitmapData data = bmp.LockBits(new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
            s.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
            bmp.UnlockBits(data);
            return bmp;
        }



        /// <summary>
        /// 拍照功能
        /// </summary>
        private void GetPic()
        {
            try
            {
                if (videoSourcePlayer.IsRunning)
                {
                    IntPtr ip = videoSourcePlayer.GetCurrentVideoFrame().GetHbitmap();
                    this.richText_logs.Text = "[" + DateTime.Now + "]拍照功能运行中...";
                    BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                                    ip,
                                    IntPtr.Zero,
                                     Int32Rect.Empty,
                                    BitmapSizeOptions.FromEmptyOptions());
                    DeleteObject(ip);
                     PngBitmapEncoder pE = new PngBitmapEncoder();
                    
                    pE.Frames.Add(BitmapFrame.Create(bitmapSource));
                    string picName = GetImagePath() + "\\" + "pic"+DateTime.Now.ToString("yyyyMMddhhmmss") + ".jpg";
                    //string picName = GetImagePath() + "\\" + "cert.jpg";
                    
                    if (File.Exists(picName))
                    {
                        File.Delete(picName);
                    }
                    using (Stream stream = File.Create(picName))
                    {
                        pE.Save(stream);
                        //SetLosResult("[" + DateTime.Now + "]拍照完成：" + picName);
                        this.richText_logs.Text = "[" + DateTime.Now + "]拍照完成：" + picName;
                    }
                    //拍照完成后关摄像头并刷新同时关窗体
                    //if (videoSourcePlayer != null && videoSourcePlayer.IsRunning)
                    //{
                    //    videoSourcePlayer.SignalToStop();
                    //    videoSourcePlayer.WaitForStop();
                    //}

                    //this.Close();
                }

             
            }
            catch (Exception ex)
            {
                MessageBox.Show("摄像头异常：" + ex.Message);
            }
        }




        private void videoSourcePlayer1_NewFrame(object sender, ref Bitmap image)
        {

            //录像
            Graphics g = Graphics.FromImage(image);
            SolidBrush drawBrush = new SolidBrush(Color.Yellow);

            Font drawFont = new Font("Arial", 6, System.Drawing.FontStyle.Bold, GraphicsUnit.Millimeter);
            int xPos = image.Width - (image.Width - 15);
            int yPos = 10;
            //写到屏幕上的时间
            drawDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

            g.DrawString(drawDate, drawFont, drawBrush, xPos, yPos);
            if (!Directory.Exists(videoPath))
                Directory.CreateDirectory(videoPath);

            //创建文件路径
            //fileFullPath = path + fileName;

            if (stopREC)
            {
                stopREC = true;
                createNewFile = true;  //这里要设置为true表示要创建新文件
                if (videoWriter != null)
                    videoWriter.Close();
            }
            else
            {

                try
                {

                    //开始录像
                    if (createNewFile)
                    {
                        videoFileName = DateTime.Now.ToString("yyyyMMddHH") + ".avi";
                        videoFileFullPath = videoPath + videoFileName;
                        createNewFile = false;
                        if (videoWriter != null)
                        {
                            videoWriter.Close();
                            videoWriter.Dispose();
                        }
                        videoWriter = new VideoFileWriter();
                        //这里必须是全路径，否则会默认保存到程序运行根据录下了
                        videoWriter.Open(videoFileFullPath, image.Width, image.Height, frameRate, VideoCodec.MPEG4);
                        videoWriter.WriteVideoFrame(image);
                    }
                    else
                    {
                        videoWriter.WriteVideoFrame(image);
                    }
                }
                catch (Exception ex) { 
                    
                     
                
                }

            }


            g.Dispose();
        }

        private string GetImagePath()
        {
            string personImgPath = "";

            personImgPath = this.tb_filePath.Text.Trim();
            if (string.IsNullOrEmpty(personImgPath))
            {
                personImgPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory)
                              + Path.DirectorySeparatorChar.ToString() + "PersonImg";
            }
            if (!Directory.Exists(personImgPath))
            {
                Directory.CreateDirectory(personImgPath);
            }

            return personImgPath;
        }


        private void WriteLogsResult(object text)
        {
            this.toolStripStatusLabel1.Text = text.ToString();
        }
        private void SetLosResult(string text)
        {
            try
            {
                this.statusStrip1.Invoke(new WriteLabelDelegate(WriteLogsResult), text);
            }
            catch
            {
            }
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dialog = new FolderBrowserDialog();
            dialog.Description = "请选择文件路径";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                string foldPath = dialog.SelectedPath;
                this.tb_filePath.Text = foldPath;
                db.C("save_path", foldPath);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //开始录像
            if (btnStartVideotape.Text == "开始录像")
            {
                stopREC = false;
                //frameRate = Convert.ToInt32(txtFrameRate.Text.Trim());
                btnStartVideotape.Text = "停止录像";
            }
            else if (btnStartVideotape.Text == "停止录像")
            {
                stopREC = true;
                btnStartVideotape.Text = "开始录像";
            }
        }

        private void videoSourcePlayer_Click(object sender, EventArgs e)
        {

        }




        //注册热键
        private void register_hotkey()
        {

            string hk = db.C("hotkey")[0][1]; //CTRL+ O

            hk = hk.Replace("[", "");
            hk = hk.Replace("]", "");
            string[] sArray = Regex.Split(hk, ",", RegexOptions.IgnoreCase);
            if (sArray.Length < 2)
            {

                return;

            }
            hotkey.KeyModifiers k;
            switch (Int32.Parse(sArray[0]))
            {

                case 0: k = hotkey.KeyModifiers.None; break;
                case 1: k = hotkey.KeyModifiers.Alt; break;
                case 2: k = hotkey.KeyModifiers.Ctrl; break;
                case 4: k = hotkey.KeyModifiers.Shift; break;
                case 8: k = hotkey.KeyModifiers.WindowsKey; break;
                default: k = hotkey.KeyModifiers.None; break;
            }

            handler = this.Handle;
            hotkey.RegisterHotKey(handler, 247696111, k, (Keys)(Int32.Parse(sArray[1])));
        }



        //重写消息循环
        protected override void WndProc(ref Message m)
        {
            const int WM_HOTKEY = 0x0312;
            // m.WParam.ToInt32() 要和 注册热键时的第2个参数一样
            if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == 247696111) //判断热键
            {
                    //如果按下热键
                    if (this.Opacity == 1)
                    {
                        Console.WriteLine("hide");
                        //this.WindowState = FormWindowState.Minimized;
                        this.Opacity = 0;
                        this.ShowInTaskbar = false;
                        //此时 handle 发生了变化 要注销旧的handle
                        hotkey.UnregisterHotKey(handler, 247696111);
                        register_hotkey();
                    }
                    else
                    {

                        Console.WriteLine("show");
                        //this.WindowState = FormWindowState.Normal;
                        this.Opacity = 1;

                        this.ShowInTaskbar = true;
                        //此时 handle 又发生了变化 要注销旧的handle
                        hotkey.UnregisterHotKey(handler, 247696111);
                        register_hotkey();

                    }

               
            }
            base.WndProc(ref m);
        }

        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
            this.keyValue = new StringBuilder();
            Keys k = e.KeyCode;
            Console.WriteLine((int)k);
            hotkey.KeyModifiers modifierKeys = hotkey.KeyModifiers.None;   //0 null  1 alt  2 CTRL  4 SHIFT  8  WindowsKey
            int c = 0;

            if (e.Modifiers != 0)
            {
                if (e.Control)
                {
                    keyValue.Append("Ctrl + ");
                    modifierKeys = hotkey.KeyModifiers.Ctrl;
                }

                if (e.Alt)
                {
                    keyValue.Append("Alt + ");
                    modifierKeys = hotkey.KeyModifiers.Alt;
                }

                if (e.Shift)
                {

                    keyValue.Append("Shift + ");
                    modifierKeys = hotkey.KeyModifiers.Shift;
                }


            }

            if ((int)e.KeyCode == 13 || (e.KeyValue >= 33 && e.KeyValue <= 40) ||
               (e.KeyValue >= 65 && e.KeyValue <= 90) ||   //a-z/A-Z
               (e.KeyValue >= 112 && e.KeyValue <= 123))   //F1-F12
            {
                keyValue.Append(e.KeyCode);
                c = e.KeyValue;
            }
            else if ((e.KeyValue >= 48 && e.KeyValue <= 57))    //0-9
            {
                keyValue.Append(e.KeyCode.ToString().Substring(1));
                c = e.KeyValue;
            }
            else if (c != 0)
            {

                MessageBox.Show("热键只能是 [Ctrl,Alt,Shift] + [单个字母，单个数字，F1-F12,Enter] 组合而成，如:CTRL + B,ALT + C,CTR + F1");
                return;
            }

            this.textBox1.Text = keyValue.ToString();


            //开始注册热键
            //hotkey.RegisterHotKey(Handle, 103, modifierKeys, e.KeyCode);

            //Console.WriteLine("注册热键成功：" + keyValue.ToString());

            //把值变成json保存到数据库

            //this.kv = new int[] { (int)modifierKeys, c };
            
            if (db.C("hotkey")[0][1] != "[" + (int)modifierKeys + "," + c + "]" && c != 0) {
                db.C("hotkey", "[" + (int)modifierKeys + "," + c + "]");
            }



        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

            

        }

        private void textBox1_Click(object sender, EventArgs e)
        {
            this.textBox1.Text = "";
        }

        private void textBox1_Leave(object sender, EventArgs e)
        {
            showHotKey();
        }


      

        
    }
}
